package services.impl;

import java.util.List;
import java.util.Vector;

import javax.ejb.EJB;
import javax.ejb.Stateless;

import services.ExchangeFormatService;
import services.OrdenCompraService;
import services.ProveedorService;
import services.RodamientoService;
import services.VentaService;
import JMS.JMSService;
import dao.OrdenCompraDAO;
import entities.ItemOrdenCompra;
import entities.ItemVenta;
import entities.OrdenCompra;
import entities.Proveedor;
import entities.Rodamiento;
import entities.RodamientoStock;
import entities.Venta;
import entities.xml.OrdenCompraXML;
import entities.xml.VentaXML;
import finals.Finals;

@Stateless
public class OrdenCompraServiceBean implements OrdenCompraService{
	
	@EJB
	private OrdenCompraDAO ordenCompraDAO;
	@EJB
	private RodamientoService rodamientoService;
	@EJB
	private ProveedorService proveedorService;
	@EJB
	private VentaService ventaService;
	@EJB
	private ExchangeFormatService exchangeFormatService;
	@EJB
	private JMSService jmsService;
	
	@Override
	public void generarYEnviarOC(List<ItemVenta> itemsVenta) {
		List<OrdenCompra> ordenes = this.generarOC(itemsVenta);
		this.enviarOCAProveedores(ordenes);
		
	}
	
	@Override
	public List<OrdenCompra> generarOC(List<ItemVenta> itemsVenta) {
		List<OrdenCompra> ordenes = new Vector<OrdenCompra>();
		for (ItemVenta item : itemsVenta) {
			RodamientoStock rodamiento = (RodamientoStock) rodamientoService.findRodamientoStock(item.getRodamiento());			
			if (rodamiento.getStock()>=item.getCantidad()){
				rodamientoService.disminuirStock(item.getCantidad(), rodamiento);
			}
			else{
				this.disminuirStockGenerandoOC(ordenes, item, rodamiento);
			}			
		}		
		if (!ordenes.isEmpty()){
			this.persistAll(ordenes);
		}
		
		return ordenes;
	}
	
	public void enviarOCAProveedores(List<OrdenCompra> ordenes){
		for(OrdenCompra orden : ordenes){
			String ordenXML = exchangeFormatService.toEF(orden, new OrdenCompraXML());
			//String razonSocialProveedor = orden.getProveedor().getRazonSocial();
			jmsService.enviarJMS(ordenXML, Finals.COLAS.get("proveedorEJBOrdenesCompra"), Finals.IPS.get("proveedorEJBOrdenesCompra"));
		}
	}
	
	/**
	 * Setea el stock del rodamiento en 0.
	 * Con la cantidad que falte de stock generara una OC. Si ya hay una OC con el mismo proveedor
	 * en el array ordenes que se le pasa como parametro, no se crea otra OC por separado, sino que
	 * se busca esa OC en el array y se le agrega el item. De lo contrario, se crea una nueva OC y
	 * se agrega al array ordenes.
	 */
	private void disminuirStockGenerandoOC(List<OrdenCompra> ordenes, ItemVenta itemVenta, RodamientoStock rodamiento){
		//Separo al item entre el que va a la factura y el que va a la OC
			//Factura
		int stockFaltante = rodamientoService.disminuirStock(itemVenta.getCantidad(), rodamiento);
			//Orden de Compra
		ItemOrdenCompra itemOC = new ItemOrdenCompra(rodamiento, stockFaltante, itemVenta.getListaPreciosId());
		Proveedor proveedor = proveedorService.findByListaPreciosID(itemVenta.getListaPreciosId());
		proveedor = proveedorService.findByRazonSocial(proveedor.getRazonSocial());
		OrdenCompra oc = new OrdenCompra(proveedor);
		int ocIndice = this.verificarSiYaHayOCEnProcesoParaProveedor(ordenes, oc);
		if (ocIndice >=0){
			oc =ordenes.get(ocIndice);
		}else{
			oc.setItems(new Vector<ItemOrdenCompra>());
			ordenes.add(oc);
		}
		oc.getItems().add(itemOC);
	}
	
	/**
	 * Se hace una OC por cada proveedor distinto al que se necesite pedir.
	 * Este metodo verifica si en el loop en el que esta metido ya cree una OC con el proveedor
	 * que esta seteado en el parametro oc.
	 */
	private int verificarSiYaHayOCEnProcesoParaProveedor(List<OrdenCompra> ordenes, OrdenCompra oc){
		for(int i = 0; i < ordenes.size(); i++){
			if(ordenes.get(i).getProveedor().getRazonSocial().equals(oc.getProveedor().getRazonSocial())){
				return i;
			}
		}
		return -1;
	}
	
	@Override
	public void delete(Object id) {
		ordenCompraDAO.delete(id);
	}

	@Override
	public List<OrdenCompra> findAll() {
		return ordenCompraDAO.findAll();
	}

	@Override
	public OrdenCompra findByID(Object id) {
		return ordenCompraDAO.findByID(id);
	}

	@Override
	public void persist(OrdenCompra entity) {
		ordenCompraDAO.persist(entity);
	}

	@Override
	public OrdenCompra merge(OrdenCompra entity) {
		return ordenCompraDAO.merge(entity);
	}

	@Override
	public void persistAll(List<OrdenCompra> ordenes) {
		for(OrdenCompra ordenCompra : ordenes){
			ordenCompraDAO.persist(ordenCompra);
		}
	}
	
	@Override
	public void generarYEnviarRemito(List<ItemVenta> itemsVenta, Integer clienteId, String ofVentaAlias) {
		Venta remito = this.generarRemito(itemsVenta, clienteId);
		this.enviarRemitoAofV(remito, ofVentaAlias);
		
	}
	
	@Override
	public Venta generarRemito(List<ItemVenta> itemsVenta, Integer clienteId) {
		Venta remito = new Venta(itemsVenta, clienteId);
		for(ItemVenta itemVenta : itemsVenta){
			Rodamiento rodamientoSinId = itemVenta.getRodamiento();
			Rodamiento rodamiento = rodamientoService.find(rodamientoSinId);
			itemVenta.setRodamiento(rodamiento);
		}
		ventaService.persist(remito);
		
		return remito;
	}

	@Override
	public void enviarRemitoAofV(Venta remito, String ofVentaAlias) {
		String strRemitoXML = exchangeFormatService.toEF(remito, new VentaXML());
		jmsService.enviarJMS(strRemitoXML, Finals.COLAS.get(ofVentaAlias), Finals.IPS.get(ofVentaAlias));
	}
}
